package com.n9.qq.android.login;

import com.n9.qq.android.Const;
import com.n9.qq.android.login.tlv.*;
import com.n9.qq.util.Crypter;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author ice
 * @since 2019/2/15 11:39
 */
public class ReqLoginBody extends BaseReqLoginBody {
    private byte[] pwMd5;
    private byte[] tgtgtKey;
    private int requestId;

    private long serverCurTime;


    private byte[] imeiMd5;
    private byte[] macMd5;
    private byte[] androIdMd5;
    private byte[] bssidMd5;
    private byte[] ssid;

    public ReqLoginBody(long qqUin, byte[] pwMd5, byte[] tgtgtKey, int requestId, long serverCurTime, byte[] imeiMd5, byte[] macMd5, byte[] androIdMd5, byte[] bssidMd5, byte[] ssid) {
        this.qqUin = qqUin;
        this.pwMd5 = pwMd5;
        this.tgtgtKey = tgtgtKey;
        this.requestId = requestId;
        this.serverCurTime = serverCurTime;
        this.imeiMd5 = imeiMd5;
        this.macMd5 = macMd5;
        this.androIdMd5 = androIdMd5;
        this.bssidMd5 = bssidMd5;
        this.ssid = ssid;

        unKnowData = (byte) 0x87;
    }

    @Override
    protected byte[] encryptData(byte[] shareKey) {
        int[] cmds = new int[]{0x0018, 0x0001, 0x0106, 0x0116, 0x0100, 0x0107, 0x0108, 0x0104, 0x0142, 0x0144, 0x0145,
                0x0147, 0x0154, 0x0141, 0x0008, 0x0511, 0x0188, 0x0194, 0x0191, 0x0177, 0x0516, 0x0521};
        List<byte[]> datasegments = new ArrayList<>();

        int len = 0;
        for (int i = 0; i < cmds.length; i++) {
            int cmd = cmds[i];

            byte[] data = null;
            switch(cmd) {
                case 0x0018:
                    data = new Tlv0018().getData(0x00000010L, 0, qqUin, 0);
                    break;
                case 0x0001:
                    data = new Tlv0001().getData(qqUin, new byte[4], serverCurTime);
                    break;
                case 0x0106:
                    data = new Tlv0106().getData(qqUin, pwMd5, tgtgtKey, imeiMd5, serverCurTime, Const.APPID);
                    break;
                case 0x0116:
                    data = new Tlv0116().getData(Const.M_MISC_BIT_MAP, Const.M_SUB_SIG_MAP, null);
                    break;
                case 0x0100:
                    data = new Tlv0100().getData(0x00000010, Const.APPID, 0x00000000, 0x001E10E0);
                    break;
                case 0x0107:
                    data = new Tlv0107().getData(0, 0, 0, 1);
                    break;
                case 0x0108:
                    break;
                case 0x0104:
                    break;
                case 0x0142:
                    data = new Tlv0142().getData(Const.APP_PACKAGE_NAME.getBytes());
                    break;
                case 0x0112:
                    break;
                case 0x0144:
                    Tlv0109 tlv0109 = new Tlv0109();
                    byte[] ds0109Data = tlv0109.getData(imeiMd5);
                    Tlv0124 tlv0124 = new Tlv0124();
                    byte[] ds0124Data = tlv0124.getData(Const.OS_TYPE.getBytes(), Const.OS_VERSION.getBytes(), Const.NET_WORK_TYPE, Const.SIM_NAME.getBytes(), new byte[0], Const.APN_NAME.getBytes());
                    Tlv0128 tlv0128 = new Tlv0128();
                    byte[] ds0128Data = tlv0128.getData(0, 1, 0, 0x01000000, Const.PHONE_TYPE.getBytes(), imeiMd5, Const.PHONE_BRANDS.getBytes());
                    Tlv016e tlv016E = new Tlv016e();
                    byte[] ds016eData = tlv016E.getData(Const.PHONE_TYPE.getBytes());

                    Tlv0144 tlv0144 = new Tlv0144();
                    data = tlv0144.getData(ds0109Data, ds0124Data, ds0128Data, ds016eData, tgtgtKey);
                    break;
                case 0x0145:
                    data = new Tlv0145().getData(imeiMd5);
                    break;
                case 0x0147:
                    data = new Tlv0147().getData(0x00000010, Const.APP_VERSION.getBytes(), Const.PKG_SIGN);
                    break;
                case 0x0166:
                    break;
                case 0x016A:
                    break;
                case 0x0154:
                    data = new Tlv0154().getData(requestId);
                    break;
                case 0x0141:
                    data = new Tlv0141().getData(Const.SIM_NAME.getBytes(), Const.NET_WORK_TYPE, Const.APN_NAME.getBytes());
                    break;
                case 0x0008:
                    data = new Tlv0008().getData(0, 0x00000804, 0);
                    break;
                case 0x0511:
                    data = new Tlv0511().getData(Const.DOMAINS);
                    break;
                case 0x0516:
                    data = new Tlv0516().getData();
                    break;
                case 0x0521:
                    data = new Tlv0521().getData();
                    break;
                case 0x0172:
                    break;
                case 0x0185:
                    break;
                case 0x0400:
                    break;
                case 0x0187:
                    data = new Tlv0187().getData(macMd5);
                    break;
                case 0x0188:
                    data = new Tlv0188().getData(androIdMd5);
                    break;
                case 0x0194:
                    data = new Tlv0194().getData(Const.IMSI_MD5);
                    break;
                case 0x0191:
                    data = new Tlv0191().getData(true);
                    break;
                case 0x0201:
                    break;
                case 0x0202:
                    data = new Tlv0202().getData(bssidMd5, ssid);
                    break;
                case 0x0177:
                    data = new Tlv0177().getData(Const.RELEASE_TIME, Const.SDK_VERSION);
                    break;
                default:
                    break;
            }

            if (Objects.nonNull(data)) {
                datasegments.add(data);
                len += data.length;
            }
        }

        ByteBuffer buf = ByteBuffer.allocate(len + 4);
        buf.putShort((short)0x0009);
        buf.putShort((short)datasegments.size());
        for (byte[] d : datasegments) {
            buf.put(d);
        }

        return new Crypter().encrypt(buf.array(), shareKey);
    }

}
